import Router from '@koa/router'
import type { RouterContext } from '@koa/router'
import { defaultStorage as storage, DeviceRecord } from '../infra/storage.mjs'
import { DeviceConfigMessage } from '../types/device-config.mjs'
import { deviceGateway } from '../ws/device-gateway.mjs'
import { logger } from '../infra/logger.mjs'

interface RegisterDeviceBody {
  deviceId?: unknown
  name?: unknown
  hardwareInfo?: unknown
}

type DeviceConfigBody = DeviceConfigMessage | undefined

const deviceRouter = new Router()

deviceRouter.post('/', async (ctx) => {
  const body = ctx.request.body as RegisterDeviceBody | undefined
  const deviceId = typeof body?.deviceId === 'string' ? body.deviceId.trim() : ''
  const name = typeof body?.name === 'string' ? body.name.trim() : undefined
  const hardwareInfo = isPlainObject(body?.hardwareInfo) ? (body?.hardwareInfo as Record<string, any>) : null

  if (!deviceId) {
    ctx.status = 400
    ctx.body = {
      success: false,
      msg: 'deviceId 不可为空',
      data: null
    }
    return
  }

  const user = ctx.state.user as { id: number }
  if (!user?.id) {
    ctx.status = 401
    ctx.body = {
      success: false,
      msg: '未授权',
      data: null
    }
    return
  }

  const device = await storage.ensureDevice(deviceId, name ?? null, hardwareInfo ?? null)
  await storage.bindUserToDevice(user.id, device)

  ctx.body = {
    success: true,
    msg: '设备绑定成功',
    data: null
  }
})

deviceRouter.post('/config', async (ctx) => {
  const configBody = ctx.request.body as DeviceConfigBody
  if (!isValidConfigMessage(configBody)) {
    ctx.status = 400
    ctx.body = {
      success: false,
      msg: '无效的配置格式',
      data: null
    }
    return
  }

  const user = ctx.state.user as { id: number }
  const targetDevice = await resolveTargetDevice(ctx, user?.id)
  if (!targetDevice) {
    return
  }

  const existingConfig = await storage.getDeviceConfig(targetDevice)
  const mergedConfigs = mergeConfigs(existingConfig?.configs ?? [], configBody)
  await storage.upsertDeviceConfig(targetDevice, mergedConfigs, 'USER')

  const pushed = deviceGateway.sendConfig(targetDevice.deviceId, [configBody])
  logger.info('DeviceRouter_config_update', {
    deviceId: targetDevice.deviceId,
    pushed
  })

  ctx.body = {
    success: true,
    msg: '配置已更新',
    data: null
  }
})

deviceRouter.get('/config', async (ctx) => {
  const user = ctx.state.user as { id: number }
  const targetDevice = await resolveTargetDevice(ctx, user?.id)
  if (!targetDevice) {
    return
  }

  const config = await storage.getDeviceConfig(targetDevice)
  ctx.body = {
    success: true,
    msg: 'ok',
    data: {
      config: config?.configs ?? []
    }
  }
})

deviceRouter.get('/status', async (ctx) => {
  const user = ctx.state.user as { id: number }
  const targetDevice = await resolveTargetDevice(ctx, user?.id)
  if (!targetDevice) {
    return
  }

  const device = await storage.findDeviceByDeviceIdentifier(targetDevice.deviceId)
  const online = Boolean(device?.lastStatus?.online)

  ctx.body = {
    success: true,
    msg: 'ok',
    data: {
      online
    }
  }
})

async function resolveTargetDevice(ctx: RouterContext, userId?: number): Promise<DeviceRecord | undefined> {
  if (!userId) {
    ctx.status = 401
    ctx.body = {
      success: false,
      msg: '未授权',
      data: null
    }
    return undefined
  }

  const queryDeviceId = extractQueryDeviceId(ctx.query.deviceId)
  if (queryDeviceId) {
    const device = await storage.getBoundDeviceForUser(userId, queryDeviceId)
    if (!device) {
      ctx.status = 404
      ctx.body = {
        success: false,
        msg: '未找到对应设备',
        data: null
      }
      return undefined
    }
    return device
  }

  const boundDevices = await storage.listBoundDevicesForUser(userId)
  if (boundDevices.length === 0) {
    ctx.status = 404
    ctx.body = {
      success: false,
      msg: '当前账号未绑定设备',
      data: null
    }
    return undefined
  }

  if (boundDevices.length > 1) {
    ctx.status = 400
    ctx.body = {
      success: false,
      msg: '绑定了多个设备，请通过 deviceId 指定目标设备',
      data: null
    }
    return undefined
  }

  return boundDevices[0]
}

function mergeConfigs(existing: DeviceConfigMessage[], nextConfig: DeviceConfigMessage): DeviceConfigMessage[] {
  const filtered = existing.filter((config) => config.type !== nextConfig.type)
  return [...filtered, nextConfig]
}

function extractQueryDeviceId(deviceIdParam: unknown): string | undefined {
  if (typeof deviceIdParam === 'string') {
    return deviceIdParam.trim() || undefined
  }
  if (Array.isArray(deviceIdParam) && deviceIdParam.length > 0) {
    return typeof deviceIdParam[0] === 'string' ? deviceIdParam[0].trim() || undefined : undefined
  }
  return undefined
}

function isValidConfigMessage(config: DeviceConfigBody): config is DeviceConfigMessage {
  if (!config || typeof config !== 'object') {
    return false
  }
  if (!('type' in config) || !('config' in config)) {
    return false
  }
  return true
}

function isPlainObject(value: unknown): value is Record<string, any> {
  return typeof value === 'object' && value !== null && !Array.isArray(value)
}

export { deviceRouter }

